﻿using System;
using System.Net.Sockets;

namespace H.Nets
{

    /// <summary>
    /// 消息接收处理函数委托
    /// </summary>
    /// <param name="topicID">接收到的消息的话题ID</param>
    /// <param name="typeID">接收到的消息的类型</param>
    /// <param name="dataLength">接收到的消息的长度</param>
    /// <param name="buffer">存储消息的缓冲区</param>
    /// <returns>
    /// 返回需要发送的内容,支持三种类型:string,byte[],int,
    /// <para>string:直接返回某段文字</para>
    /// <para>byte[]:直接返回某段原始数据</para>
    /// <para>int:将数据写入在buffer中,返回了写入的数据的长度</para>
    /// </returns>
    public delegate void DataRecieveHandler(int topicID, int typeID, int dataLength, byte[] buffer);

    /// <summary>
    /// 当客户端状态发生改变时的处理函数
    /// </summary>
    public delegate void ClientStatusHandler(bool status);

    /// <summary>
    /// 代表一个网络服务客户端
    /// </summary>
    public interface ITcpClient : IDisposable
    {
        /// <summary>
        /// 读取或设置客户端名称
        /// </summary>
        string Identifier { get; set; }

        /// <summary>
        /// 当前客户端是否可以使用
        /// </summary>
        bool IsValid { get; }

        /// <summary>
        /// 客户端是否存在一个连接
        /// </summary>
        bool Connected { get; }

        /// <summary>
        /// 当接收到服务端发来的消息时
        /// </summary>
        event DataRecieveHandler Recieved;

        /// <summary>
        /// 当客户端连接状态发生改变时
        /// </summary>
        event ClientStatusHandler StatusChange;

        /// <summary>
        /// 当客户端改名时,发射此事件
        /// </summary>
        event ClientRenameHandler Rename;

        /// <summary>
        /// 开始连接服务器
        /// </summary>
        void Connect();

        /// <summary>
        /// 断开服务器连接
        /// </summary>
        /// <exception cref="SocketException"></exception>
        void Disconnect();

        /// <summary>
        /// 创建一个新的主题,对于非回复性的消息,都应该重新创建一个主题,
        /// 此接口效率极高,放心使用
        /// </summary>
        /// <returns>返回一个新的主题ID</returns>
        int CreateTopic();

        /// <summary>
        /// 发送或回复一个消息(不携带数据)
        /// </summary>
        /// <param name="topicID">话题ID,如果用同一个TopicID,则表示回复某个消息,请使用CreateTopic接口创建话题</param>
        /// <param name="typeID">消息的类型,这个消息类型是服务器和客户端之间自己约定的,方便快速路由消息</param>
        /// <returns>返回是否发送成功</returns>
        bool Send(int topicID, int typeID);

        /// <summary>
        /// 发送或回复一个消息(任意格式数据)
        /// </summary>
        /// <param name="topicID">话题ID,如果用同一个TopicID,则表示回复某个消息,请使用CreateTopic接口创建话题</param>
        /// <param name="typeID">消息的类型,这个消息类型是服务器和客户端之间自己约定的,方便快速路由消息</param>
        /// <param name="dataLength">将要被发送的数据</param>
        /// <param name="buffer">将要被发送的数据所在的缓冲区,需要结合dataLength使用</param>
        /// <returns>返回是否发送成功</returns>
        bool Send(int topicID, int typeID, int dataLength, byte[] buffer);

        /// <summary>
        /// 发送或回复一个消息
        /// </summary>
        /// <param name="topicID">话题ID,如果用同一个TopicID,则表示回复某个消息,请使用CreateTopic接口创建话题</param>
        /// <param name="typeID">消息的类型,这个消息类型是服务器和客户端之间自己约定的,方便快速路由消息</param>
        /// <param name="message">需要发送的消息</param>
        /// <returns></returns>
        bool Send(int topicID, int typeID, string message);


        /// <summary>
        /// 发送一个消息(任意格式数据)
        /// </summary>
        /// <param name="typeID">消息的类型,这个消息类型是服务器和客户端之间自己约定的,方便快速路由消息</param>
        /// <param name="dataLength">将要被发送的数据</param>
        /// <param name="buffer">将要被发送的数据所在的缓冲区,需要结合dataLength使用</param>
        /// <returns>返回是否发送成功</returns>
        bool Send(int typeID, int dataLength, byte[] buffer);

        /// <summary>
        /// 发送一个消息
        /// </summary>
        /// <param name="typeID">消息的类型,这个消息类型是服务器和客户端之间自己约定的,方便快速路由消息</param>
        /// <param name="message">需要发送的消息</param>
        /// <returns>返回是否发送成功</returns>
        bool Send(int typeID, string message);

        /// <summary>
        /// 通知远端客户端准备开始接收大小 小于size的数据块,
        /// 发送超过32K大小的数据时,必须使用此函数扩大缓冲区,
        /// 当结束发送大量数据之后,宜调用EndBulkTransfer函数恢复缓冲区大小
        /// 设置远端客户端的接收缓冲区,避免造成数据丢失
        /// </summary>
        /// <returns>返回是否发送成功</returns>
        bool BeginBulkTransfer(int size);

        /// <summary>
        /// 结束发送大量数据
        /// </summary>
        /// <returns>返回是否发送成功</returns>
        bool EndBulkTransfer();

        /// <summary>
        /// 发送某个消息并等待其返回结果
        /// </summary>
        /// <param name="topicID">进行处理并相应的主题ID</param>
        /// <param name="typeID">发送的消息类型ID和反馈的消息类型ID</param>
        /// <param name="dataLength">发送的数据长度/返回的数据长度</param>
        /// <param name="buffer">需要发送的数据/返回的数据,其大小可能会重新被分配</param>
        /// <param name="millisecondsTimeout">等待的超时时间,传入-1表示无期限等待</param>
        /// <returns>返回是否执行成功</returns>
        bool Exchange(int topicID, ref int typeID, ref int dataLength, ref byte[] buffer, int millisecondsTimeout = -1);

        /// <summary>
        /// 等待某个主题的反馈后继续
        /// </summary>
        /// <param name="topicID">等待的主题</param>
        /// <param name="typeID">返回的类型ID</param>
        /// <param name="dataLength">返回的数据长度</param>
        /// <param name="buffer">用于返回数据的缓冲区,如果空间大小不足,将会重新分配</param>
        /// <param name="millisecondsTimeout">等待的超时时间,传入-1表示无期限等待</param>
        /// <returns>返回是否执行成功</returns>
        bool Recieve(int topicID, out int typeID, out int dataLength, ref byte[] buffer, int millisecondsTimeout = -1);


    }
}
